#include "json_bean.h"
#include <stdio.h>
#include <malloc.h>
#include <string.h>
#include "cjson/cJSON.h"


/************************************************
 * 功能：构造函数
 * 输入参数：
 *      type：Data -- 普通类型，Array -- JSON数组类型
 * ***********************************************/
JsonBean::JsonBean(JsonBean::Type eType)
{
    m_strJsonData.clear();
    m_pJson = NULL;
    m_bOk = true;

    if(eType == Array)
    {
        m_pJson = cJSON_CreateArray();
    }
    else
    {
        m_pJson = cJSON_CreateObject();
    }
}

/************************************************
 * 功能：构造函数
 * 输入参数：
 *      strJsonData：JSON数据
 * ***********************************************/
JsonBean::JsonBean(const std::string &strJsonData)
{
    m_strJsonData.clear();
    m_pJson = nullptr;
    m_bOk = false;

    m_strJsonData = strJsonData;
    m_pJson = cJSON_Parse(m_strJsonData.c_str());
    m_bOk = m_pJson ? true : false;
}

/************************************************
 * 功能：拷贝构造函数
 * 输入参数：
 *      objOther：JSON对象
 * ***********************************************/
JsonBean::JsonBean(const JsonBean &objOther)
{
    m_strJsonData = objOther.m_strJsonData;
    m_bOk = objOther.m_bOk;

    if(objOther.m_pJson)
    {
        m_pJson = cJSON_Duplicate(objOther.m_pJson, 1);
    }
    else
    {
        m_pJson = nullptr;
    }
}

/************************************************
 * 功能：赋值构造函数
 * 输入参数：
 *      objOther：JSON对象
 * 返回值：
 *      JsonBean：新的JSON对象
 * ***********************************************/
JsonBean& JsonBean::operator=(const JsonBean &objOther)
{
    if(this == &objOther)
    {
        return *this;
    }

    m_strJsonData = objOther.m_strJsonData;
    m_bOk = objOther.m_bOk;

    if(m_pJson)
    {
        cJSON_Delete(m_pJson);
    }

    if(objOther.m_pJson)
    {
        m_pJson = cJSON_Duplicate(objOther.m_pJson, 1);
    }
    else
    {
        m_pJson = nullptr;
    }

    //返回本对象的引用
    return *this;
}

/************************************************
 * 功能：析构函数
 * ***********************************************/
JsonBean::~JsonBean()
{
    m_strJsonData.clear();

    if(m_pJson)
    {
        cJSON_Delete(m_pJson);
        m_pJson = nullptr;
        m_bOk = false;
    }
}

/************************************************
 * 功能：解析json是否正常
 * 返回值：
 *      bool：解析结果，true -- 正常，false -- 异常
 * ***********************************************/
bool JsonBean::isJsonOk() const
{
    return m_bOk;
}

/************************************************
 * 功能：读取JSON数据
 * 返回值：
 *      std::string：JSON数据
 * ***********************************************/
std::string JsonBean::data()
{
    if(m_pJson)
    {
        char* pData = cJSON_Print(m_pJson);
        m_strJsonData = std::string(pData);
        free(pData);
    }

    return m_strJsonData;
}

/************************************************
 * 功能：读取对应无格式的JSON数据
 * 返回值：
 *      std::string：无格式JSON数据
 * ***********************************************/
std::string JsonBean::unformattedData()
{
    if(m_pJson)
    {
        char* pData = cJSON_PrintUnformatted(m_pJson);
        m_strJsonData = std::string(pData);
        free(pData);
    }

    return m_strJsonData;
}

/************************************************
 * 功能：返回JSON数组子对象个数
 * 返回值：
 *      int：JSON数组子对象个数
 * ***********************************************/
int JsonBean::count() const
{
    int iCount = 0;
    if(m_pJson)
    {
        iCount = cJSON_GetArraySize(m_pJson);
    }

    return iCount;
}

/************************************************
 * 功能：读取JSON数组子对象
 * 输入参数：
 *      iIndex：JSON数组子对象索引
 * 返回值：
 *      JsonBean：JSON数组子对象
 * ***********************************************/
JsonBean JsonBean::at(int iIndex) const
{
    JsonBean objBean;
    if(m_pJson)
    {
        cJSON* pItem = cJSON_GetArrayItem(m_pJson, iIndex);
        if(pItem)
        {
            cJSON_Delete(objBean.m_pJson);
            objBean.m_pJson = cJSON_Duplicate(pItem, 1);
        }
    }

    return objBean;
}

/************************************************
 * 功能：判断是否是JSON数组类型
 * 返回值：
 *      bool：是否JOSN数组，true -- 是，false -- 否
 * ***********************************************/
bool JsonBean::isArray() const
{
    bool bArray = false;
    if(m_pJson)
    {
        bArray = (m_pJson->type & 0xFF) == cJSON_Array;
    }

    return bArray;
}

/************************************************
 * 功能：添加空数据
 * 输入参数：
 *      strKey：键值
 * ***********************************************/
void JsonBean::addNull(const std::string &strKey)
{
    if(m_pJson)
    {
        cJSON_AddNullToObject(m_pJson, strKey.c_str());
    }

    return;
}

/************************************************
 * 功能：添加string型键值数据
 * 输入参数：
 *      strKey：键值
 *      pValue：数据
 * ***********************************************/
void JsonBean::add(const std::string &strKey, const char *pValue)
{
    if(m_pJson)
    {
        if(pValue)
        {
            cJSON_AddStringToObject(m_pJson, strKey.c_str(), pValue);
        }
    }

    return;
}

/************************************************
 * 功能：设置string型键值数据
 * 输入参数：
 *      strKey：键值
 *      pValue：数据
 * ***********************************************/
void JsonBean::set(const std::string &strKey, const char *pValue)
{
    if(m_pJson)
    {
        cJSON* pSon = cJSON_GetObjectItem(m_pJson, strKey.c_str());
        if(!pSon)
        {
            add(strKey, pValue);
        }
        else
        {
            if(pValue)
            {
                if(pSon->valuestring)
                {
                    free(pSon->valuestring);
                }

                size_t uiLen = strlen(pValue) + 1;

                pSon->valuestring = static_cast<char*>(malloc(uiLen));
                if(pSon->valuestring)
                {
                    memset(pSon->valuestring, 0, uiLen);
                    memcpy(pSon->valuestring, pValue, uiLen - 1);
                }
            }
        }
    }

    return;
}

/************************************************
 * 功能：添加string型键值数据
 * 输入参数：
 *      strKey：键值
 *      strValue：数据
 * ***********************************************/
void JsonBean::add(const std::string &strKey, const std::string &strValue)
{
    if(m_pJson)
    {
        cJSON_AddStringToObject(m_pJson, strKey.c_str(), strValue.c_str());
    }

    return;
}

/************************************************
 * 功能：设置string型键值数据
 * 输入参数：
 *      strKey：键值
 *      strValue：数据
 * ***********************************************/
void JsonBean::set(const std::string &strKey, const std::string &strValue)
{
    if(m_pJson)
    {
        cJSON* pSon = cJSON_GetObjectItem(m_pJson, strKey.c_str());
        if(!pSon)
        {
            add(strKey, strValue);
        }
        else
        {
            if(pSon->valuestring)
            {
                free(pSon->valuestring);
            }

            size_t uiLen = strlen(strValue.c_str()) + 1;

            pSon->valuestring = static_cast<char*>(malloc(uiLen));
            if(pSon->valuestring)
            {
                memset(pSon->valuestring, 0, uiLen);
                memcpy(pSon->valuestring, strValue.c_str(), uiLen - 1);
            }
        }
    }

    return;
}

/************************************************
 * 功能：添加double型键值数据
 * 输入参数：
 *      strKey：键值
 *      dValue：数据
 * ***********************************************/
void JsonBean::add(const std::string &strKey, const double &dValue)
{
    if(m_pJson)
    {
        cJSON_AddNumberToObject(m_pJson, strKey.c_str(), dValue);
    }

    return;
}

/************************************************
 * 功能：设置double型键值数据
 * 输入参数  ：
 *      strKey：键值
 *      dValue：数据
 * ***********************************************/
void JsonBean::set(const std::string &strKey, const double &dValue)
{
    if(m_pJson)
    {
        cJSON* pSon = cJSON_GetObjectItem(m_pJson, strKey.c_str());
        if(!pSon)
        {
            add(strKey, dValue);
        }
        else
        {
            pSon->valueint = static_cast<int>(dValue);
            pSon->valuedouble = dValue;
        }
    }

    return;
}

/************************************************
 * 功能：添加int型键值数据
 * 输入参数  ：
 *      strKey：键值
 *      iValue：数据
 * ***********************************************/
void JsonBean::add(const std::string &strKey, const int &iValue)
{
    if(m_pJson)
    {
        cJSON_AddNumberToObject(m_pJson, strKey.c_str(), iValue);
    }

    return;
}

/************************************************
 * 功能：设置int型键值数据
 * 输入参数  ：
 *      strKey：键值
 *      iValue：数据
 * ***********************************************/
void JsonBean::set(const std::string &strKey, const int &iValue)
{
    if(m_pJson)
    {
        cJSON* pSon = cJSON_GetObjectItem(m_pJson, strKey.c_str());
        if(!pSon)
        {
            add(strKey, iValue);
        }
        else
        {
            pSon->valueint = iValue;
            pSon->valuedouble = iValue;
        }
    }

    return;
}

/************************************************
 * 功能：添加bool型键值数据
 * 输入参数：
 *      strKey：键值
 *      bValue：数据
 * ***********************************************/
void JsonBean::add(const std::string &strKey, const bool &bValue)
{
    if(m_pJson)
    {
        cJSON_AddBoolToObject(m_pJson, strKey.c_str(), bValue);
    }

    return;
}

/************************************************
 * 功能：设置bool型键值数据
 * 输入参数：
 *      strKey：键值
 *      bValue：数据
 * ***********************************************/
void JsonBean::set(const std::string &strKey, const bool &bValue)
{
    if(m_pJson)
    {
        cJSON* pSon = cJSON_GetObjectItem(m_pJson, strKey.c_str());
        if(!pSon)
        {
            add(strKey, bValue);
        }
        else
        {
            pSon->type = bValue ? cJSON_True : cJSON_False;
        }
    }

    return;
}

/************************************************
 * 功能：添加JSON型键值数据
 * 输入参数  ：
 *      strKey：键值
 *      objValue：数据
 * ***********************************************/
void JsonBean::add(const std::string &strKey, const JsonBean &objValue)
{
    if(m_pJson)
    {
        cJSON* pJson = cJSON_Duplicate(objValue.m_pJson, 1);
        if(pJson)
        {
            cJSON_AddItemToObject(m_pJson, strKey.c_str(), pJson);
        }
    }

    return;
}

/************************************************
 * 功能：设置JSON型键值数据
 * 输入参数  ：
 *      strKey：键值
 *      objValue：数据
 * ***********************************************/
void JsonBean::set(const std::string &strKey, const JsonBean &objValue)
{
    if(m_pJson)
    {
        cJSON* pSon = cJSON_GetObjectItem(m_pJson, strKey.c_str());
        if(pSon)
        {
            cJSON_DeleteItemFromObject(m_pJson, strKey.c_str());
        }

        add(strKey, objValue);
    }

    return;
}

/************************************************
 * 功能：添加子对象数据到当前JSON数组中
 * 输入参数：
 *      objChildValue：子对象
 *
 *
    使用示例：
    QJson arrayJson(QJson::Array);
    for(int i = 0 ; i < 3 ; ++i)
    {
     QJson itemJson;
     itemJson.add(key1, value1);
     itemJson.add(key2, value2);

     arrayJson.addItemToArray(itemJson);
    }

    QJson resultJson;
    resultJson.add(key, arrayJson);
 * ***********************************************/
void JsonBean::addDataToArray(const JsonBean &objChildValue)
{
    if(m_pJson && isArray())
    {
        cJSON* pJson = cJSON_Duplicate(objChildValue.m_pJson, 1);
        if(pJson)
        {
            cJSON_AddItemToArray(m_pJson, pJson);
        }
    }

    return;
}

/************************************************
 * 功能：添加字符串数组到JSON中，例如{"arrVal":["str1", "str2", "str3"]}
 * 输入参数：
 *      strValue：字符串值
 * ***********************************************/
void JsonBean::addDataToArray(const std::string &strValue)
{
    if(m_pJson && isArray())
    {
        cJSON_AddItemToArray(m_pJson, cJSON_CreateString(strValue.c_str()));
    }

    return;
}

/************************************************
 * 功能：添加int数组到JSON中，例如{"intVal":[1, 2, 3]}
 * 输入参数：
 *      iValue：int数据
 * ***********************************************/
void JsonBean::addDataToArray(const int &iValue)
{
    if(m_pJson && isArray())
    {
        cJSON_AddItemToArray(m_pJson, cJSON_CreateNumber(iValue));
    }

    return;
}

/************************************************
 * 功能：添加double数组到JSON中，例如{"doubleVal":[1.2, 2.3, 3.4]}
 * 输入参数：
 *      dValue：double数据
 * ***********************************************/
void JsonBean::addDataToArray(const double &dValue)
{
    if(m_pJson && isArray())
    {
        cJSON_AddItemToArray(m_pJson, cJSON_CreateNumber(dValue));
    }

    return;
}

/************************************************
 * 功能：添加bool数组到JSON中，例如{"boolVal":[true, false, true]}
 * 输入参数：
 *      bValue：bool数据
 * ***********************************************/
void JsonBean::addDataToArray(const bool &bValue)
{
    if(m_pJson && isArray())
    {
        cJSON_AddItemToArray(m_pJson, cJSON_CreateBool(bValue));
    }

    return;
}

/************************************************
 * 功能：数据转换为字符串值
 * 返回值：
 *      std::string：转换后的数据
 * ***********************************************/
std::string JsonBean::toString() const
{
    std::string strData = "";

    if(m_pJson)
    {
        if(cJSON_String == (m_pJson->type & 0xFF))
        {
            strData = std::string(m_pJson->valuestring);
        }
    }

    return strData;
}

/************************************************
 * 功能：数据转换为bool
 * 返回值：
 *      bool：转换后的数据
 * ***********************************************/
bool JsonBean::toBool() const
{
    bool bData = false;
    if(m_pJson)
    {
        if(((m_pJson->type & 0xFF) == cJSON_True) || ((m_pJson->type & 0xFF) == cJSON_False))
        {
            bData = ((m_pJson->type & 0xFF) == cJSON_True);
        }
    }

    return bData;
}

/************************************************
 * 功能：数据转换为int
 * 返回值：
 *      int：转换后的数据
 * ***********************************************/
int JsonBean::toInt() const
{
    int iData = 0;
    if(m_pJson)
    {
        if((m_pJson->type & 0xFF) == cJSON_Number)
        {
            //iData = m_pJson->valueint;//not valid in sometime
            iData = static_cast<int>(m_pJson->valuedouble);
        }
    }

    return iData;
}

/************************************************
 * 功能：数据转换为double
 * 返回值：
 *      double：转换后的数据
 * ***********************************************/
double JsonBean::toDouble() const
{
    double dData = 0;
    if(m_pJson)
    {
        if((m_pJson->type & 0xFF) == cJSON_Number)
        {
            dData = m_pJson->valuedouble;
        }
    }

    return dData;
}

/************************************************
 * 功能：读取子JSON对象
 * 输入参数：
 *      strKey：键值
 * 返回值：
 *      JsonBean：对应的子对象
 * ***********************************************/
JsonBean JsonBean::value(const std::string &strKey)
{
    JsonBean objBean;
    if(m_pJson)
    {
        cJSON* pJson = cJSON_GetObjectItem(m_pJson, strKey.c_str());
        if(pJson)
        {
            cJSON_Delete(objBean.m_pJson);
            objBean.m_pJson = cJSON_Duplicate(pJson, 1);
        }
    }

    return objBean;
}

/************************************************
 * 功能：JSON对象是否存在
 * 输入参数：
 *      strKey：键值
 * 返回值：
 *      bool：是否存在，true -- 存在，false -- 不存在
 * ***********************************************/
bool JsonBean::isExist(const std::string &strKey)
{
    bool bRet = false;
    if(m_pJson)
    {
        cJSON* pJson = cJSON_GetObjectItem(m_pJson, strKey.c_str());
        bRet = pJson ? true : false;
    }

    return bRet;
}


